package drds.data_migrate.util;


import drds.common.$;
import drds.common.Author;
import drds.data_migrate.Authors;
import drds.data_migrate.vo.TaskConfig;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Author(name = Authors.LI_YANG)
public final class Updates
{


    public static String table_name_placeholder = "@tableName";

    public static List<TaskConfig> doSplit(
            int adviceNumber)
    {

        List<TaskConfig> splitResultTaskConfigs = new ArrayList<TaskConfig>();

        int tableNumber = 0;

        //处理单表的情况
        if (tableNumber == 1)
        {
            //由于在之前的  master prepare 中已经把 tableName,jdbcUrl 提取出来，所以这里处理十分简单
            for (int j = 0; j < adviceNumber; j++)
            {
                splitResultTaskConfigs.add(null);
            }

            return splitResultTaskConfigs;
        }

        if (tableNumber != adviceNumber)
        {
//            throw DataExchangeException.asDataExchangeException(DBUtilErrorCode.CONF_ERROR,
//                    String.format("您的配置文件中的列配置信息有误. 您要写入的目的端的表个数是:%s , 但是根据系统建议需要切分的份数是：%s. 请检查您的配置并作出修改.",
//                            tableNumber, adviceNumber));

            throw new RuntimeException();
        }

        String jdbcUrl;
        List<String> preSqlList = null;
        List<String> postSqlList = null;

        List<Object> connectionInfoList = null;

        for (Object connectionInfo : connectionInfoList)
        {
            TaskConfig sliceTaskConfig = null;

            TaskConfig connConf = (TaskConfig) connectionInfo;
            jdbcUrl = connConf.getJdbcUrl();
            sliceTaskConfig.setJdbcUrl(jdbcUrl);

            //sliceTaskConfig.remove(Constant.connection);

            List<String> tableNameList = connConf.getTableNameList();

            for (String tableName : tableNameList)
            {
                TaskConfig tempSlice = sliceTaskConfig;
                tempSlice.setTableName(tableName);
                tempSlice.setPreSqlList(replaceTableName(preSqlList, tableName));
                tempSlice.setPostSqlList(replaceTableName(postSqlList, tableName));

                splitResultTaskConfigs.add(tempSlice);
            }

        }

        return splitResultTaskConfigs;
    }

    public static List<String> replaceTableName(List<String> preOrPostSqlList, String tableName)
    {
        if ($.isHasData(preOrPostSqlList))
        {
            return Collections.emptyList();
        }

        List<String> renderedSqlList = new ArrayList<String>();
        for (String sql : preOrPostSqlList)
        {
            renderedSqlList.add(sql.replace(table_name_placeholder, tableName));
        }

        return renderedSqlList;
    }

    public static void executeSqlList(Connection connection, List<String> sqlList) throws SQLException
    {
        Statement statement = null;

        try
        {
            statement = connection.createStatement();
            for (String sql : sqlList)
            {

                Jdbc.execute(statement, sql);
            }
        } catch (SQLException e)
        {
            throw e;
        } finally
        {
            Jdbc.close(null, statement, null);
        }
    }

    public static String getWriteTemplate(List<String> columnNameList, List<String> valueList, String writeMode, boolean forceUseUpdate)
    {
        boolean isWriteModeLegal = writeMode.startsWith("insert") || writeMode.startsWith("replace") || writeMode.startsWith("update");
        if (!isWriteModeLegal)
        {
            throw new IllegalArgumentException("仅支持replace,insert,update");
        }

        String sql;
        if (forceUseUpdate ||
                writeMode.trim().toLowerCase().startsWith("update"))

        {
            //update只在mysql下使用

            sql = new StringBuilder().append("insert into %s (").append(StringUtils.join(columnNameList, ",")).append(") values(").append(StringUtils.join(valueList, ",")).append(")").append(onDuplicateKeyUpdateString(columnNameList)).toString();
        } else
        {

            //这里是保护,如果其他错误的使用了update,需要更换为replace
            if (writeMode.trim().toLowerCase().startsWith("update"))
            {
                writeMode = "replace";
            }
            sql = new StringBuilder().append(writeMode).append(" into %s (").append(StringUtils.join(columnNameList, ",")).append(") values(").append(StringUtils.join(valueList, ",")).append(")").toString();
        }

        return sql;
    }

    public static String onDuplicateKeyUpdateString(List<String> columnNameList)
    {
        if (columnNameList == null || columnNameList.size() < 1)
        {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(" on duplicate key update ");
        boolean first = true;
        for (String columnName : columnNameList)
        {
            if (!first)
            {
                sb.append(",");
            } else
            {
                first = false;
            }
            sb.append(columnName);
            sb.append("=values(");
            sb.append(columnName);
            sb.append(")");
        }

        return sb.toString();
    }

    public static void preCheckPrePareSQL()
    {

        String tableName = null;

        List<String> preOrPostSqlList = null;
        List<String> sqlList = Updates.replaceTableName(
                preOrPostSqlList, tableName);
        if ($.isHasData(sqlList))
        {
            for (String sql : sqlList)
            {

                try
                {
                    Jdbc.execute(null, sql);
                } catch (SQLException e)
                {
                    e.printStackTrace();
                }
            }
        }


    }

    public static void preCheckPostSQL()
    {

        String tableName = null;

        List<String> postSqlList = null;
        List<String> sqlList = Updates.replaceTableName(postSqlList, tableName);
        if ($.isHasData(sqlList))
        {
            for (String sql : sqlList)
            {

                try
                {
                    Jdbc.execute(null, sql);
                } catch (SQLException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }


}
